using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.DependencyModel;
using Serilog;

namespace ASPApiDemo.Common.Core;

// 运行时扩展类，提供程序集和类型加载的辅助方法
public static class RuntimeExtension
{
    // 获取项目程序集，排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
    public static IList<Assembly> GetAllAssemblies()
    {
        var list = new List<Assembly>();
        var deps = DependencyContext.Default;
        // 获取默认的依赖关系上下文，只加载项目中的程序集
        // 筛选编译库，排除所有的系统程序集(Serviceable=true)和Nuget下载包，只保留项目类型的库
        var libs = deps.CompileLibraries
            .Where(lib => !lib.Serviceable && lib.Type == "project");
        // 遍历所有筛选出的项目库
        foreach (var lib in libs)
        {
            try
            {
                // 使用默认的程序集加载上下文加载程序集
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                // 将加载的程序集添加到列表中
                list.Add(assembly);
            }
            catch (Exception e)
            {
                // 记录异常信息到日志
                Log.Debug(e, "GetAllAssemblies Exception:{ex}", e.Message);
            }
        }

        return list;
    }
    // 根据程序集名称获取特定的程序集
    public static Assembly GetAssembly(string assemblyName)
    {
        // 从所有程序集中查找第一个名称包含指定字符串的程序集
        return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
    }
    // 获取所有程序集中定义的所有类型
    public static IList<Type> GetAllTypes()
    {
        // 创建一个新的类型列表
        var list = new List<Type>();
        // 遍历所有程序集
        foreach (var assembly in GetAllAssemblies())
        {
            // 获取程序集中定义的所有类型信息
            var typeInfos = assembly.DefinedTypes;
            // 遍历所有类型信息
            foreach (var typeInfo in typeInfos)
            {
                // 将类型信息转换为Type并添加到列表中
                list.Add(typeInfo.AsType());
            }
        }

        return list;
    }
    // 根据程序集名称获取该程序集中的所有类型
    public static IList<Type> GetTypesByAssembly(string assemblyName)
    {
        var list = new List<Type>();
        // 使用默认的程序集加载上下文加载指定名称的程序集
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
        // 获取程序集中定义的所有类型信息
        var typeInfos = assembly.DefinedTypes;
        // 遍历所有类型信息
        foreach (var typeInfo in typeInfos)
        {
            // 将类型信息转换为Type并添加到列表中
            list.Add(typeInfo.AsType());
        }

        return list;
    }
    // 获取实现了指定接口的特定名称的类型
    public static Type GetImplementType(string typeName, Type baseInterfaceType)
    {
        // 从所有类型中查找符合条件的第一个类型
        return GetAllTypes().FirstOrDefault(t =>
        {
            // 检查类型名称是否匹配且实现了指定的接口
            if (t.Name == typeName &&
                t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
            {
                // 获取类型信息
                var typeInfo = t.GetTypeInfo();
                // 确保类型是一个非抽象、非泛型的类
                return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
            }

            // 如果不符合条件，返回false
            return false;
        });
    }
}